#[[
文件系统: file system: FS。

一、目录和文件: directory and file。

二、系统数据文件和信息: system data file and information。

三、进程环境: process environment
]]

#[[
                        目录和文件
参考书籍: APUE/SCAPP

文件:
* 如何获取文件属性? get file attributes

一个命令: 例如: cmd --长格式的选项 -短格式的选项 (非选项的传参)

touch -a
这样是失败的。

touch -- -a
创建一个文件名为 -a 的文件。

或者这样写
touch ./-a
也是可以的。

删除的时候:
rm ./-a
或者
rm -- -a

---
获取文件属性的便利函数:
man 2 stat

另外, stat也是一个linux命令, 这个命令是使用 stat();函数 封装出来的。例如:
stat filename

[liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$ ls
cmake-build-debug  CMakeLists.txt  src
[liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$ stat CMakeLists.txt
  File: CMakeLists.txt
  Size: 489             Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d    Inode: 818854      Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  liuyou)   Gid: ( 1000/  liuyou)
Access: 2021-12-09 16:51:00.324109154 +0800
Modify: 2021-12-09 16:50:56.000000000 +0800
Change: 2021-12-09 16:50:56.992003902 +0800
 Birth: -
[liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$


NAME
       stat, fstat, lstat, fstatat - get file status
       获取文件的属性状态。

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       // 通过文件名(或者是文件的根路径)来获取文件属性。
       int stat(const char *pathname, struct stat *statbuf);
       // 通过文件描述符来获取文件属性。
       int fstat(int fd, struct stat *statbuf);
       // lstat();和stat();的区别在于对链接文件的处理上是不同的。
       int lstat(const char *pathname, struct stat *statbuf);

       #include <fcntl.h>           /* Definition of AT_* constants */
       #include <sys/stat.h>

       int fstatat(int dirfd, const char *pathname, struct stat *statbuf,
                   int flags);

DESCRIPTION
       These  functions  return information about a file, in the buffer pointed to by statbuf.  No permissions are required on the file itself, but—in the case of stat(), fstatat(), and
       lstat()—execute (search) permission is required on all of the directories in pathname that lead to the file.
       这些函数在 statbuf 指向的缓冲区中返回有关文件的信息。文件本身不需要权限，
       但在 stat()、fstatat() 和 lstat() 的情况下，需要对路径名中指向文件的所有目录执行（搜索）权限。

       stat() and fstatat() retrieve information about the file pointed to by pathname; the differences for fstatat() are described below.
       stat() 和 fstatat() 检索有关路径名指向的文件的信息； fstatat() 的区别如下所述。

       lstat() is identical to stat(), except that if pathname is a symbolic link, then it returns information about the link itself, not the file that it refers to.
       lstat() 与 stat() 相同，除了如果路径名是符号链接，则它返回有关链接本身的信息，而不是它所引用的文件。

       fstat() is identical to stat(), except that the file about which information is to be retrieved is specified by the file descriptor fd.
       fstat() 与 stat() 相同，不同之处在于要检索信息的文件由文件描述符 fd 指定。

   The stat structure
   stat结构体:
       All of these system calls return a stat structure, which contains the following fields:
       所有这些系统调用都返回一个 stat 结构，其中包含以下字段:

           struct stat {

               dev_t     st_dev;         /* ID of device containing file */     包含文件的设备 ID

               // ls -i 得到的 inode号就是这个字段。
               ino_t     st_ino;         /* Inode number */                     inode号

               // 文件的权限信息, 即 ll 得到的例如:
                [liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$ ll
                total 4
                drwxrwxr-x 6 liuyou liuyou 169 Dec  9 16:51 cmake-build-debug
                -rw-rw-r-- 1 liuyou liuyou 489 Dec  9 16:50 CMakeLists.txt
                drwxrwxr-x 7 liuyou liuyou  84 Dec  9 16:49 src
                [liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$
                中 的 drwxrwxr-x。
               // st_mode 类型是一个位图。
               // 那么mode_t是多少位的整型数呢? 8位还是16位还是32位?
               // 其实mode_t是一个16位的整型数。
               //
                drwxrwxr-x
                -rw-rw-r--
                drwxrwxr-x
               // 第一位是文件类型,
               // 然后3位是user对这个文件的权限。
               // 然后3位是同组用户对这个文件的权限。
               // 然后3位是other用户对这个文件的权限。
               // st_mode 由两部分组成: 一部分是文件的类型、还有一部分是文件的权限。
               // 即 drwxrwxr-x 中的 d 和 rwxrwxr-x。
               //
               // 文件类型分为 7 种: dcb-lsp。
               // d: directory
               // c: character(字符设备文件)
               // b: block(块设备文件)
               // -: regular(常规文件)
               // l: link(链接文件, 在这仅仅指的是符号链接文件)
               // s: socket(网络套接字socket文件)
               // p: pipe(管道文件, 在这指的是匿名管道, 匿名管道在磁盘上是看不到的)

               // 所以, mode_t 是多少位的整形数呢?
               // 7种文件类型(用3位表示即可), 然后加上 9 位对文件的访问权限,
               // 然后加上 3 位特殊权限: 即 3 + 9 + 3 = 15, 即 16位。

       // 摘自 man 7 inode
       Because tests of the above form are common, additional macros are defined by POSIX to allow the test of the file type in st_mode to  be  written  more
       concisely:
       因为上面形式的测试很常见，所以POSIX定义了额外的宏，让st_mode中文件类型的测试写得更简洁:

           S_ISREG(m)  is it a regular file? 是普通文件吗?

           S_ISDIR(m)  directory? 目录?

           S_ISCHR(m)  character device? 字符设备?

           S_ISBLK(m)  block device? 块设备?

           S_ISFIFO(m) FIFO (named pipe)? FIFO（命名管道）?

           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.) 符号链接?

           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.) 套接字文件?

               // todo 笔记: st_mode字段是一个16位的位图, 用于表示文件类型, 文件访问权限, 以及特殊权限位。
               mode_t    st_mode;        /* File type and mode */               文件类型和模式

               // 硬链接数。即 drwxrwxr-x 6 liuyou liuyou 中的 6。
               nlink_t   st_nlink;       /* Number of hard links */             硬链接数

               // 即 user id, 即 drwxrwxr-x 6 liuyou liuyou
               // 中的第一个 liuyou
               uid_t     st_uid;         /* User ID of owner */                 所有者(拥有者)的用户 ID

               // 即 group id, 即 drwxrwxr-x 6 liuyou liuyou
               // 中的第二个 liuyou
               gid_t     st_gid;         /* Group ID of owner */                所有者(拥有者)的组 ID

               // 如果拿到的内容真正是设备的时候, 那么这个字段就是设备的ID号。
               dev_t     st_rdev;        /* Device ID (if special file) */      设备 ID（如果是特殊文件）

               // st_size字段即为 -rw-rw-r-- 1 liuyou liuyou 489 Dec  9 16:50 CMakeLists.txt
               // 中的 489, 以字节为单位。
               off_t     st_size;        /* Total size, in bytes */             总大小，以字节为单位

               // 一个block(一个块)有多大, 一般情况下是 512 个字节。
               blksize_t st_blksize;     /* Block size for filesystem I/O */    文件系统 IO 的块大小

               // 当前这个文件占用了多少个 512 的块。
               // st_blocks字段指的是扇区数。
               //
               // st_blocks和st_blksize这两个字段决定了文件在磁盘上所占用的大小。
               blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */  分配的 512B 块数

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */
                  从 Linux 2.6 开始，内核支持以下时间戳字段的纳秒精度。
                  Linux 2.6 之前的详细信息，请参见 NOTES。

               //
               struct timespec st_atim;  /* Time of last access */              上次访问时间

               // 最后一次修改的时间: -rw-rw-r-- 1 liuyou liuyou 489 Dec  9 16:50 CMakeLists.txt
               // 即为 Dec  9 16:50 的时间。
               struct timespec st_mtim;  /* Time of last modification */        最后修改时间


               struct timespec st_ctim;  /* Time of last status change */       上次状态更改时间

           #define st_atime st_atim.tv_sec      /* Backward compatibility(向后兼容) */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

       Note: the order of fields in the stat structure varies somewhat across architectures.  In addition, the definition above does not show the  padding  bytes  that  may  be  present
       between some fields on various architectures.  Consult the glibc and kernel source code if you need to know the details.
       注意：stat 结构中字段的顺序在不同架构之间有所不同。此外，上面的定义没有显示各种体系结构上某些字段之间可能存在的填充字节。如果需要了解详细信息，请查阅 glibc 和内核源代码。

       Note: for performance and simplicity reasons, different fields in the stat structure may contain state information from different moments during the execution of the system call.
       For example, if st_mode or st_uid is changed by another process by calling chmod(2) or chown(2), stat() might return the old st_mode together with the  new  st_uid,  or  the  old
       st_uid together with the new st_mode.
       注意：出于性能和简单的原因，stat 结构中的不同字段可能包含系统调用执行期间不同时刻的状态信息。例如，如果另一个进程通过调用 chmod(2) 或 chown(2) 更改了 st_mode 或 st_uid，则 stat() 可能会返回旧的 st_mode 和新的 st_uid，或者旧的 st_uid 和新的 st_mode。

       The fields in the stat structure are as follows:
       stat结构体中的字段如下:

       st_dev This field describes the device on which this file resides.  (The major(3) and minor(3) macros may be useful to decompose the device ID in this field.)
       此字段描述此文件所在的设备。 （major(3) 和 minor(3) 宏可能有助于分解此字段中的设备 ID。）

       st_ino This field contains the file's inode number.
       此字段包含文件的 inode 编号。

       st_mode
              This field contains the file type and mode.  See inode(7) for further information.
              此字段包含文件类型和模式。有关详细信息，请参阅 inode(7)。

       st_nlink
              This field contains the number of hard links to the file.
              此字段包含文件的硬链接数。

       st_uid This field contains the user ID of the owner of the file.
       此字段包含文件所有者的用户 ID。

       st_gid This field contains the ID of the group owner of the file.
       此字段包含文件组所有者的 ID。

       st_rdev
              This field describes the device that this file (inode) represents.
              此字段描述此文件（inode）代表的设备。

       st_size
              This  field gives the size of the file (if it is a regular file or a symbolic link) in bytes.  The size of a symbolic link is the length of the pathname it contains, with‐
              out a terminating null byte.
              此字段以字节为单位给出文件的大小（如果它是常规文件或符号链接）。符号链接的大小是它包含的路径名的长度，没有终止的空字节。

       st_blksize
              This field gives the "preferred" block size for efficient filesystem I/O.
              此字段以字节为单位给出文件的大小（如果它是常规文件或符号链接）。符号链接的大小是它包含的路径名的长度，没有终止的空字节。

       st_blocks
              This field indicates the number of blocks allocated to the file, in 512-byte units.  (This may be smaller than st_size/512 when the file has holes.)
              此字段指示分配给文件的块数，以 512 字节为单位。 （当文件有漏洞时，这可能小于 st_size512。）

       st_atime
              This is the file's last access timestamp.
              这是文件的最后访问时间戳。

       st_mtime
              This is the file's last modification timestamp.
              这是文件的最后修改时间戳。

       st_ctime
              This is the file's last status change timestamp.
              这是文件的最后状态更改时间戳。

       For further information on the above fields, see inode(7).
       有关上述字段的更多信息，请参阅 inode(7)。

   fstatat()
       The fstatat() system call is a more general interface for accessing file information which can still provide exactly the behavior of each of stat(), lstat(), and fstat().

       If the pathname given in pathname is relative, then it is interpreted relative to the directory referred to by the file descriptor dirfd (rather  than  relative  to  the  current
       working directory of the calling process, as is done by stat() and lstat() for a relative pathname).

       If  pathname  is  relative and dirfd is the special value AT_FDCWD, then pathname is interpreted relative to the current working directory of the calling process (like stat() and
       lstat()).

       If pathname is absolute, then dirfd is ignored.

       flags can either be 0, or include one or more of the following flags ORed:

       AT_EMPTY_PATH (since Linux 2.6.39)
              If pathname is an empty string, operate on the file referred to by dirfd (which may have been obtained using the open(2) O_PATH flag).  In this case, dirfd  can  refer  to
              any type of file, not just a directory, and the behavior of fstatat() is similar to that of fstat().  If dirfd is AT_FDCWD, the call operates on the current working direc‐
              tory.  This flag is Linux-specific; define _GNU_SOURCE to obtain its definition.

       AT_NO_AUTOMOUNT (since Linux 2.6.38)
              Don't automount the terminal ("basename") component of pathname if it is a directory that is an automount point.  This allows the caller to gather attributes of  an  auto‐
              mount  point (rather than the location it would mount).  Since Linux 4.14, also don't instantiate a nonexistent name in an on-demand directory such as used for automounter
              indirect maps.  This flag can be used in tools that scan directories to prevent mass-automounting of a directory of automount points.   The  AT_NO_AUTOMOUNT  flag  has  no
              effect  if the mount point has already been mounted over.  This flag is Linux-specific; define _GNU_SOURCE to obtain its definition.  Both stat() and lstat() act as though
              AT_NO_AUTOMOUNT was set.

       AT_SYMLINK_NOFOLLOW
              If pathname is a symbolic link, do not dereference it: instead return information about the link itself, like lstat().  (By default, fstatat() dereferences symbolic links,
              like stat().)

       See openat(2) for an explanation of the need for fstatat().

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
       成功时，返回零。出错时，返回 -1，并适当设置 errno。

ERRORS
       EACCES Search permission is denied for one of the directories in the path prefix of pathname.  (See also path_resolution(7).)

       EBADF  fd is not a valid open file descriptor.

       EFAULT Bad address.

       ELOOP  Too many symbolic links encountered while traversing the path.

       ENAMETOOLONG
              pathname is too long.

       ENOENT A component of pathname does not exist, or pathname is an empty string and AT_EMPTY_PATH was not specified in flags.

       ENOMEM Out of memory (i.e., kernel memory).

       ENOTDIR
              A component of the path prefix of pathname is not a directory.

       EOVERFLOW
              pathname  or fd refers to a file whose size, inode number, or number of blocks cannot be represented in, respectively, the types off_t, ino_t, or blkcnt_t.  This error can
              occur when, for example, an application compiled on a 32-bit platform without -D_FILE_OFFSET_BITS=64 calls stat() on a file whose size exceeds (1<<31)-1 bytes.

       The following additional errors can occur for fstatat():

       EBADF  dirfd is not a valid file descriptor.

       EINVAL Invalid flag specified in flags.

       ENOTDIR
              pathname is relative and dirfd is a file descriptor referring to a file other than a directory.






* 文件的访问权限问题? file access permissions

对tat结构体中的 st_mode 字段的理解。

* umask

创建一个新文件或者在终端cat一个文件, 这个文件的umask是如何确认的呢?
0666 & ~unmask

[liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$ umask
0002
[liuyou@iZwz91q87vgg7an0q1ce5hZ LinuxEnvironmentProgramming2]$



* 文件权限的更改/管理(chmod();、fchmod();)

* 粘住位

* 文件系统: 以FAT文件系统和UFS文件系统为例。

目录:
* 什么是硬链接? 什么是符号链接?

* utime

* 目录的创建和销毁 directory creation and destroy

* 更改当前工作路径 change current working directory

* 解析目录/读取目录内容 parse directory and read the content of directory
]]

# 文件长度
add_executable(FS-FileLength1 src/FS-FileLength1.cpp)
# 大文件/空洞文件
add_executable(FS-BigFile1 src/FS-BigFile1.cpp)
# 文件类型
add_executable(FS-FileType1 src/FS-FileType1.cpp)









































































































